home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Mail / EnhanceMail.1.3 / Source / XImageURL.m < prev   
Encoding:
Text File  |  1996-04-09  |  7.3 KB  |  236 lines

  1. /* -*-C-*-
  2. *******************************************************************************
  3. *
  4. * File:         XImageURL.m
  5. * RCS:          $Header: /usr/local/lib/cvs/EnhanceMail/XImageURL.m,v 1.1.1.8 1996/04/09 16:19:00 cedman Exp $
  6. * Description:  
  7. * Author:       Carl Edman
  8. * Created:      Fri Oct 20 14:47:00 1995
  9. * Modified:     Tue Apr  9 11:52:05 1996 (Carl Edman) cedman@capitalist.princeton.edu
  10. * Language:     C
  11. * Package:      N/A
  12. * Status:       Experimental (Do Not Distribute)
  13. *
  14. * (C) Copyright 1995, but otherwise this file is perfect freeware.
  15. *
  16. *******************************************************************************
  17. */
  18.  
  19. #import <libc.h>
  20. #import "EnhanceMail.h"
  21. #import "XImageURL.h"
  22. #import "Preferences.h"
  23. #import "regexp.h"
  24. #include <netdb.h>
  25.  
  26. #define MSG_OPEN_EXTERNAL_ATTACHMENT NXLoadLocalizedStringFromTableInBundle("Alerts", nil, "Open External Attachment", NULL)
  27. #define MSG_RETRIEVE_HTTP NXLocalizedStringFromTableInBundle("Localizable", EnhanceBundle, "Retrieving %s from %s via http...", NULL, Message for HTTP retrieval)
  28.  
  29. #define LOCALCOPY(to,from,len) { to=alloca(len+1); strncpy(to,from,len); to[len]='\0'; }
  30.  
  31. static const char *imagepath[]=
  32.    {
  33.    "/tmp",
  34.    "~/Library/Mail/Images",
  35.    "/LocalLibrary/Mail/Images",
  36.    "/NextLibrary/Mail/Images",
  37.    0
  38.    };
  39.  
  40. @implementation NXImage(XImageURL)
  41. + (BOOL)grabURL:(const char *)url to:(const char *)localpath
  42.    {
  43.    static regexp *ftprx=0;
  44.    static regexp *httprx=0;
  45.  
  46.    if (!*url) return NO;
  47.    
  48.    if (ftprx==0)
  49.       ftprx=regcomp("^ftp://([^:/ ]*(:[^/@ ]*)?@)?([^/]*/)(([^/]*/)*)([^/;]*)$");
  50.  
  51.    if (regexec(ftprx,url))
  52.       {
  53.       char *host,*dir,*filename,*user,*pass,*userpass,*path;
  54.       id fetcher=[MimeFetcher new];
  55.  
  56.       if (ftprx->startp[1]&&ftprx->startp[2])
  57.          {
  58.          LOCALCOPY(user,ftprx->startp[1],ftprx->startp[2]-ftprx->startp[1]);
  59.          LOCALCOPY(pass,ftprx->startp[2]+1,ftprx->endp[2]-ftprx->startp[2]-1);
  60.          userpass=alloca(strlen(user)+strlen(pass)+2);
  61.          sprintf(userpass,"%s %s",user,pass);
  62.          }
  63.       else if (ftprx->startp[1])
  64.          {
  65.          LOCALCOPY(user,ftprx->startp[1],ftprx->endp[1]-ftprx->startp[1]-1);
  66.          userpass=[fetcher anonUserPass];
  67.          if (pass=index(userpass,' ')) pass++; else pass="anonymous";
  68.          userpass=alloca(strlen(user)+strlen(pass)+2);
  69.          sprintf(userpass,"%s %s",user,pass);
  70.          }
  71.       else
  72.          userpass=[fetcher anonUserPass];
  73.       
  74.       LOCALCOPY(host,    ftprx->startp[3],ftprx->endp[3]-ftprx->startp[3]-1);
  75.       LOCALCOPY(dir,     ftprx->startp[4],ftprx->endp[4]-ftprx->startp[4]-1);
  76.       LOCALCOPY(filename,ftprx->startp[6],ftprx->endp[6]-ftprx->startp[6]);
  77.       
  78.       LOCALCOPY(path,localpath,strlen(localpath));
  79.       
  80.       if ([fetcher ftpFrom:host directory:dir filename:filename mode:"binary" forUserPass:userpass to:path]==NO)
  81.          return NO;
  82.       
  83.       if (access(path,R_OK)!=0)
  84.          return NO;
  85.       
  86.       return YES;
  87.       }
  88.  
  89.    if (httprx==0)
  90.       httprx=regcomp("^http://([^:/ ]*)(:[0-9]+)?(/[^;]*)$");
  91.  
  92.    if (regexec(httprx,url))
  93.       {
  94.       char *hostname="localhost",*path="/",*port="80";
  95.       char buf[1024],*pos;
  96.       struct sockaddr_in http;
  97.       struct hostent *hp;
  98.       int totlen=-1,rcvlen=0,len;
  99.       int ifd=-1,ofd=-1;
  100.       BOOL success=NO;
  101.       Progressor *progress=nil;
  102.  
  103.       if (EnhanceHTTPProxy && *EnhanceHTTPProxy)
  104.          {
  105.          strcpy(buf,EnhanceHTTPProxy);
  106.          strcat(buf,url);
  107.          if (!regexec(httprx,buf)) goto httpend;
  108.          }
  109.    
  110.       if (httprx->startp[1])
  111.          LOCALCOPY(hostname,httprx->startp[1],httprx->endp[1]-httprx->startp[1]);
  112.  
  113.       if (httprx->startp[2])
  114.          LOCALCOPY(port,httprx->startp[2]+1,httprx->endp[2]-httprx->startp[2]-1);
  115.       
  116.       if (httprx->startp[3])
  117.          LOCALCOPY(path,httprx->startp[3],httprx->endp[3]-httprx->startp[3]);
  118.       
  119.       sprintf(buf,MSG_RETRIEVE_HTTP,strrchr(path,'/')+1,hostname);
  120.       if ((progress=[Progressor newWithTitle:MSG_OPEN_EXTERNAL_ATTACHMENT message:buf])==nil) goto httpend;
  121.       [progress setShowProgress:NO];
  122.       [progress beginModalSession];
  123.       
  124.       if ((hp = gethostbyname(hostname))==0) goto httpend;
  125.       bzero((char *)&http, sizeof(http));
  126.       bcopy(hp->h_addr,(char *)&http.sin_addr,hp->h_length);
  127.       http.sin_family = hp->h_addrtype;
  128.       http.sin_port = htons(atoi(port));
  129.       if ((ifd=socket(AF_INET, SOCK_STREAM, 0))==-1) goto httpend;
  130.       if (connect(ifd,(struct sockaddr *) &http,sizeof(http))==-1) goto httpend;
  131.       
  132.       sprintf(buf,"GET %s HTTP/1.0\r\nUser-Agent: EnhanceMail/%s\r\nAccept: image/tiff\r\n\r\n",path,EnhanceVersion);
  133.       write(ifd,buf,strlen(buf));
  134.  
  135.       pos=buf;
  136.       while(![progress cancelled]&&((len=read(ifd,pos,(buf+sizeof(buf))-pos))>0))
  137.          {
  138.          char *end=pos+len,*c,*d;
  139.  
  140.          for(c=buf,d=buf;c<end;c++)
  141.             {
  142.             if (*c!='\n') continue;
  143.             c[0]='\0';
  144.             if ((c>buf)&&(c[-1]=='\r')) c[-1]='\0';
  145.             if (strncasecmp(d,"HTTP/1.0 ",9)==0)
  146.                {
  147.                if (atoi(d+9)!=200) goto httpend;
  148.                }
  149.             if (strncasecmp(d,"Content-Length: ",16)==0)
  150.                {
  151.                totlen=atoi(d+16);
  152.                [progress setMinValue:0];
  153.                [progress setMaxValue:totlen];
  154.                [progress setProgress:0];
  155.                [progress setShowProgress:YES];
  156.                }
  157.             if (*d=='\0')
  158.                {
  159.                if ((ofd=open(localpath,O_WRONLY|O_CREAT|O_TRUNC,0644))==-1)
  160.                   goto httpend;
  161.                rcvlen=end-(c+1);
  162.                write(ofd,c+1,end-(c+1));
  163.                [progress setProgress:rcvlen];
  164.                
  165.                while(![progress cancelled]&&((len=read(ifd,buf,sizeof(buf)))>0))
  166.                   {
  167.                   write(ofd,buf,len);
  168.                   rcvlen+=len;
  169.                   if (totlen>0) [progress setProgress:rcvlen];
  170.                   }
  171.                success=(len==0)&&((totlen==rcvlen)||(totlen==-1));
  172.                goto httpend;
  173.                }
  174.             d=c+1;
  175.             }
  176.          
  177.          pos=buf;
  178.          if (d>buf) while (d<end) *pos++=*d++;
  179.          }
  180.  
  181.     httpend:
  182.       if (ifd!=-1) close(ifd);
  183.       if (ofd!=0) close(ofd);
  184.       if (progress!=nil) [progress endModalSession];
  185.       return success;
  186.       }
  187.    
  188.    return NO;
  189.    }
  190.  
  191. + (BOOL)grabURL:(const char *)url buffer:(char *)path
  192.    {
  193.    int i;
  194.    char *localname,*c;
  195.  
  196.    if (!*url) return NO;
  197.    localname=strcpy(alloca(strlen(url)+1),url);
  198.    for(c=localname;*c;c++) if (*c=='/') *c='_';
  199.  
  200.    for(i=0;imagepath[i];i++)
  201.       {
  202.       if ((imagepath[i][0]=='~') && (imagepath[i][1]=='/'))
  203.          {
  204.          sprintf(path,"%s%s",NXHomeDirectory(),imagepath[i]+1);
  205.          imagepath[i]=NXUniqueString(path);
  206.          }
  207.  
  208.       sprintf(path,"%s/%s",imagepath[i],localname);
  209.       if (access(path,R_OK)==0) return YES;
  210.       }
  211.  
  212.    for(i--;i>=0;i--) if (access(imagepath[i],R_OK|W_OK|X_OK)==0) break;
  213.    if (i<0) return NO;
  214.    sprintf(path,"%s/%s",imagepath[i],localname);
  215.    
  216.    if (![NXImage grabURL:url to:path])
  217.       {
  218.       int fd=open(path,O_WRONLY|O_CREAT|O_TRUNC,0644);
  219.       if (fd!=-1) close(fd);
  220.       return NO;
  221.       }
  222.  
  223.    return YES;
  224.    }
  225.  
  226. - initURL:(const char *)url
  227.    {
  228.    char path[MAXPATHLEN+1];
  229.    struct stat buf;
  230.  
  231.    if (![NXImage grabURL:url buffer:path]) return [self free];
  232.    if ((stat(path,&buf)==-1)||(buf.st_size==0)) return [self free];
  233.    return [self initFromFile:path];
  234.    }
  235. @end
  236.